package gecko;

import java.util.HashMap;
import java.util.Map;

/**
 * {@link GeckoContext} 是每次请求生成的上下文对象，服务于事件请求的整个生命周期。
 *
 * @author 陈永佳 (yoojiachen@gmail.com)
 * @version 0.0.1
 */
public abstract class GeckoContext {

    private final long mTimestamp;
    private final String mTopic;
    private final Map<String, Object> mAttributes = new HashMap<>();

    private final Outbound mOutbound = new Outbound();
    private final Inbound mInbound;

    private long mContextId;

    public GeckoContext(String topic, Inbound inbound) {
        mTopic = topic;
        mInbound = inbound;
        mTimestamp = System.currentTimeMillis();
    }

    /**
     * 读取Attributes属性对象。
     *
     * @return JSONObject
     */
    public Map<String, Object> attributes() {
        return mAttributes;
    }

    /**
     * 添加Attribute参数。
     *
     * @param name  Name
     * @param value Value
     * @see GeckoContext#addAttributes(Map)
     */
    public void addAttribute(String name, Object value) {
        mAttributes.put(name, value);
    }

    /**
     * 添加Attribute参数。
     *
     * @param attributes Attributes
     */
    public void addAttributes(Map<String, Object> attributes) {
        mAttributes.putAll(attributes);
    }

    /**
     * @return 返回请求创建的时间戳，毫秒单位。
     */
    public long timestamp() {
        return mTimestamp;
    }

    /**
     * @return 返回当前时间与Context创建时间的时差，单位：毫秒
     */
    public long escaped() {
        return System.currentTimeMillis() - timestamp();
    }

    /**
     * 当前事件的Topic。
     * Topic由事件生成时指定，它决定着事件由哪些Interceptor、Driver处理当前事件。
     *
     * @return Topic
     */
    public String topic() {
        return mTopic;
    }

    /**
     * 返回ContextId。每个请求，具有唯一的ContextId
     *
     * @return Context Id
     */
    public long contextId() {
        return mContextId;
    }

    /**
     * 返回Inbound对象。
     *
     * @return Inbound
     */
    public Inbound inbound() {
        return mInbound;
    }

    /**
     * 返回Outbound对象
     *
     * @return Outbound
     */
    public Outbound outbound() {
        return mOutbound;
    }

    void setContextId(long id) {
        mContextId = id;
    }

    ////

    abstract void onCompleted(Outbound outbound);
}
